<?php
namespace mobile\libs;

class Curl{
	private static $_model = null;
	
	// cookie 文件名称
	private $_cookieFile = null;
	
	// curl handle
	protected $ch = '';
	
	// curl 日志文件 句柄
	protected $fp = null;
	
	// curl 参数
	protected $defaultParams = [
		'data'=> [],
		'post'=> false,
		'cookie'=> false,
		'referer'=>'http://www.google.com',
		'https' => false,
		'ssl_verifypeer'=> true,
		'header'=> false,
		'transfer'=> true,
		'ip'=>true,
		'mobile'=>true,
		'timeout'=> 5,
		'http_header'=> [
			'Connection:keep-alive',
			'Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4',
			'X-Requested-With:XMLHttpRequest',
			'Accept-Encoding: identity',
			'Cache-Control:no-cache',
			'Pragma:no-cache'
		]
	];
	
	protected $agents = [];
	
	protected $params = [];
	
	// 单例模式
	public static function model($className = __CLASS__) {
		if(null === self::$_model) {
			self::$_model = new $className;
			self::$_model->init();
		}
		
		return self::$_model;
	}
	
	public function init() {
		$this->agents['mobile'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS '.rand(8,10).'_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/'.rand(11,15).'B'.rand(120,150).' Safari/601.1';
		$this->agents['pc'] = 'Mozilla/5.0 (Windows NT '.rand(6,8).'.1; WOW'.(32 * rand(1,2)).') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'.rand(51,55).'.0.2704.'.rand(60,80).' Safari/537.36';
	}
	
	// 请求
	public function request($url, $params = []) {
		$params['https'] = preg_match("#^https#", $url);
		$this->mergeParams($params);
		
		$this->ch = curl_init();
		
		$this->setOption(CURLOPT_URL, $url);
		$this->setOption(CURLOPT_TIMEOUT, $this->params['timeout']);
		$this->setOption(CURLOPT_REFERER, $this->params['referer']);
		$this->setOption(CURLOPT_HEADER, $this->params['header']);
		$this->setOption(CURLOPT_RETURNTRANSFER, $this->params['transfer']);
		$this->setOption(CURLOPT_USERAGENT, $this->createAgent());
		
		$this->_setCurlLog();
		$this->_setHttpHeader();
		$this->params['cookie'] && $this->_setCurlCookie();
		$this->params['https'] && $this->_setHttpsRequest();
		
		$this->_setRequestType();

		$contents = curl_exec($this->ch);
		$this->close();
		
		return $contents;
	}
	
	/**
	 * 合并参数
	 */
	public function mergeParams($params) {
		if(isset($params['http_header'])) {
			$params['http_header'] = array_merge($this->defaultParams['http_header'], $params['http_header']);
		}
		$this->params = array_merge($this->defaultParams, $params);
	}
	
	/**
	 * 设置curl参数
	 */
	public function setOption($key, $value) {
		curl_setopt($this->ch, $key, $value);
	}
	
	/**
	 * 记录curl 请求日志
	 */
	protected function _setCurlLog() {
		$this->fp = fopen(DIR.'/logs/curl.log', 'a+');
		$this->setOption(CURLOPT_FOLLOWLOCATION, true);
		$this->setOption(CURLOPT_VERBOSE, true);
		$this->setOption(CURLOPT_STDERR, $this->fp);
	}
	
	/**
	 * 设置HTTP 请求头
	 */
	protected function _setHttpHeader() {
		$headerIp = [];
		if($this->params['ip']) {
			$ip = $this->createIp();
			$headerIp = ['X-FORWARDED-FOR:'.$ip, 'CLIENT-IP:'.$ip];
		}
		
		$this->setOption(CURLOPT_HTTPHEADER, array_merge($this->params['http_header'], $headerIp));
	}
	
	/**
	 * 记录cookie
	 */
	protected function _setCurlCookie() {
		if(null === $this->_cookieFile) {
			$this->_cookieFile = $this->getCookieDir().'/'.MOBILE.'.cookie';
			@ unlink($this->_cookieFile);
		}
		
		$this->setOption(CURLOPT_COOKIEFILE, $this->_cookieFile);
		$this->setOption(CURLOPT_COOKIEJAR, $this->_cookieFile);
	}
	
	/**
	 * 设置HTTPS 方式的请求
	 * 模拟证书地址： http://curl.haxx.se/ca/cacert.pem
	 */
	protected function _setHttpsRequest() {
		$this->setOption(CURLOPT_SSL_VERIFYPEER, $this->params['ssl_verifypeer']);
		$this->setOption(CURLOPT_SSL_VERIFYHOST, 2);
		$this->setOption(CURLOPT_CAINFO, DIR.'/source/cacert.pem');
	}
	
	/**
	 * 设置请求类型 post|get
	 */
	protected function _setRequestType() {
		if(true == $this->params['post']) {
			$data = is_array($this->params['data']) ? http_build_query($this->params['data']) : $this->params['data'];
			if(defined('TESTER') && TESTER) var_dump($data);
			$this->setOption(CURLOPT_POST, TRUE);
			$this->setOption(CURLOPT_POSTFIELDS, $data);
		} else {
			$this->setOption(CURLOPT_HTTPGET, TRUE);
		}
	}
	
	/**
	 * 关闭资源链接
	 */
	protected function close() {
		curl_close($this->ch);
		fclose($this->fp);
	}
	
	/**
	 * 随机IP
	 */
	public function createIp() {
		$ips = array('111.85.99.174', '219.146.68.115', '121.201.24.246', '222.186.130.53', '203.195.166.83', '210.36.19.147', '123.115.82.211');
		shuffle($ips);
		return $ips[0];
	}
	
	/**
	 * 浏览器User-Agent
	 */
	public function createAgent() {
		return $this->agents[$this->params['mobile'] ? 'mobile' : 'pc'];
	}

	/**
	 * 获取 Cookie 存放目录
	 */
	public function getCookieDir() {
		$dir = DIR.'/cookie/'.substr(MOBILE, -2);
		if(!file_exists($dir)) mkdir($dir, 0755, true);
		
		return $dir;
	}
}
